package org.apereo.cas.configuration.model.support.wsfed;

import org.apereo.cas.configuration.model.core.util.EncryptionJwtSigningJwtCryptographyProperties;
import org.apereo.cas.configuration.support.RequiresModule;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * This is {@link WsFederationProperties}.
 *
 * @author Misagh Moayyed
 * @since 5.1.0
 */
@Getter
@Setter
@RequiresModule(name = "cas-server-support-ws-idp")
public class WsFederationProperties implements Serializable {

    private static final long serialVersionUID = -8679379856243224647L;

    /**
     * Settings related to the wed-fed identity provider.
     */
    private IdentityProvider idp = new IdentityProvider();

    /**
     * Settings related to the we-fed security token service.
     */
    private SecurityTokenService sts = new SecurityTokenService();

    @Getter
    @Setter
    @RequiresModule(name = "cas-server-support-ws-idp")
    public static class IdentityProvider implements Serializable {

        private static final long serialVersionUID = 5190493517277610788L;

        /**
         * At this point, by default security token service’s endpoint operate using a single
         * realm configuration and identity provider configuration is only able to recognize and request tokens for a single realm.
         * Registration of clients need to ensure this value is matched.
         */
        private String realm = "urn:org:apereo:cas:ws:idp:realm-CAS";

        /**
         * Realm name.
         */
        private String realmName = "CAS";
    }

    @Getter
    @Setter
    @RequiresModule(name = "cas-server-support-ws-sts")
    public static class SecurityTokenService implements Serializable {

        private static final long serialVersionUID = -1155140161252595793L;

        /**
         * When generating a SAML token, indicates the subject name-id format to use.
         */
        private String subjectNameIdFormat = "unspecified";

        /**
         * When generating a SAML token, indicates the subject name-id qualifier to use.
         */
        private String subjectNameQualifier = "http://cxf.apache.org/sts";

        /**
         * Set whether the provided token will be signed or not. Default is true.
         */
        private boolean signTokens = true;
        /**
         * Set whether client lifetime is accepted.
         */
        private boolean conditionsAcceptClientLifetime = true;
        /**
         * If requested lifetime exceeds shall it fail (default)
         * or overwrite with maximum lifetime.
         */
        private boolean conditionsFailLifetimeExceedance;
        /**
         * Get how long (in seconds) a client-supplied Created Element is allowed to be in the future.
         * The default is 60 seconds to avoid common problems relating to clock skew.
         */
        private String conditionsFutureTimeToLive = "PT60S";
        /**
         * Set the default lifetime in seconds for issued SAML tokens.
         */
        private String conditionsLifetime = "PT30M";
        /**
         * Set the maximum lifetime in seconds for issued SAML tokens.
         */
        private String conditionsMaxLifetime = "PT12H";

        /**
         * Whether tokens generated by STS should encrypted.
         */
        private boolean encryptTokens = true;

        /**
         * Keystore path used to sign tokens.
         */
        private String signingKeystoreFile;

        /**
         * Keystore password used to sign tokens.
         */
        private String signingKeystorePassword;

        /**
         * Keystore path used to encrypt tokens.
         */
        private String encryptionKeystoreFile;

        /**
         * Keystore password used to encrypt tokens.
         */
        private String encryptionKeystorePassword;

        /**
         * Crypto settings used to secure calls between the idp and the sts.
         */
        @NestedConfigurationProperty
        private EncryptionJwtSigningJwtCryptographyProperties crypto = new EncryptionJwtSigningJwtCryptographyProperties();

        /**
         * Realm definition settings that define this CAS server.
         */
        private RealmDefinition realm = new RealmDefinition();

        /**
         * Collection of fully-qualified claims prefixed with the appropriate
         * namespace that are expected to be released via attribute release policy.
         */
        private List<String> customClaims = new ArrayList<>();

        @Getter
        @Setter
        @RequiresModule(name = "cas-server-support-ws-sts")
        public static class RealmDefinition implements Serializable {

            private static final long serialVersionUID = -2209230334376432934L;

            /**
             * Keystore path associated with the this realm.
             */
            private String keystoreFile;

            /**
             * Keystore password associated with the this realm.
             */
            private String keystorePassword;

            /**
             * Key alias associated with the this realm.
             */
            private String keystoreAlias;

            /**
             * Key alias associated with the this realm.
             */
            private String keyPassword;

            /**
             * Issuer/name of the realm identified and registered with STS.
             */
            private String issuer = "CAS";
        }
    }
}
